package com.mytrip.webapp.listener;

import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import com.mytrip.util.Constant;
import com.mytrip.util.CookieWrapper;
import com.mytrip.util.LocaleUtil;
import com.mytrip.util.SessionMemcacheUtil;
import com.mytrip.webapp.filter.CtxSessionBag;
import com.mytrip.webapp.session.SessionBag;
import com.mytrip.webapp.session.SessionBagImpl;

public class AppRequestListener implements ServletRequestListener, HttpSessionAttributeListener{
	
	private final Log log = LogFactory.getLog(AppRequestListener.class);
	
	private static Set<String> EXCLUDE_SESSION_NAME = new HashSet<String>();
	
	static{
		EXCLUDE_SESSION_NAME.add("__sitemesh__robot");
	}

	public void requestDestroyed(ServletRequestEvent requestEvent){
		if(Constant.useSessionInMemcache()){
			SessionBagImpl sessionBag = CtxSessionBag.getSessionBag();
			if (sessionBag != null && sessionBag.isUpdated()) {
				String memcacheKey = sessionBag.getMemcacheKey();
				if (memcacheKey != null && !"".equals(memcacheKey)) {
					// put to mc
					// sessionBag.freshUpdate();
					log.info("put session to memcache,memcacheKey:"+memcacheKey+",sessionBag:"+sessionBag);
					SessionMemcacheUtil.put(memcacheKey, sessionBag);
				}
			}
		}
		CtxSessionBag.clear();
	}

	public void requestInitialized(ServletRequestEvent requestEvent){
		// CtxSessionBag.clear();
		HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();

		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e) {
			log.error("::",e);
		}

		// String url = request.getRequestURL().toString();
		// if (!(url.lastIndexOf(".action") > 0
		// || url.lastIndexOf("/dwr/") >0 )) {
		// return;
		// }

		SessionBagImpl sessionBag = null;
		
		if(Constant.useSessionInMemcache()){
			// from cookie
			CookieWrapper cookieWrapper = new CookieWrapper(request, null);
			String memcacheKey = cookieWrapper.getCookieValue(SessionMemcacheUtil.COOKIE_SESSION_KEY);
			log.info("===="+request.getRequestURI());
			log.info("sessionKey:"+memcacheKey);
			if (memcacheKey != null) {
				sessionBag = SessionMemcacheUtil.get(memcacheKey);
				log.info("get session from memcache,memcacheKey:"+memcacheKey+",sessionBag:"+sessionBag);
			}
		}else{
			sessionBag = (SessionBagImpl) request.getSession().getAttribute(SessionBag.SESSION_KEY);
		}

		if (sessionBag == null) {
			sessionBag = new SessionBagImpl();
			sessionBag.setLocale(LocaleUtil.localeFromString(null, null));
			if(!Constant.useSessionInMemcache()){
				request.getSession().setAttribute(SessionBag.SESSION_KEY,sessionBag);
			}
		}

		sessionBag.setIp(request.getRemoteAddr());
		sessionBag.setSessionNbr(request.getSession().getId());

		// 设置Locale
		Locale sessionLocale = sessionBag.getLocale();
		String reqlocaleStr = request.getParameter("request_locale");
		if (reqlocaleStr == null || "".equals(reqlocaleStr.trim())) {
			reqlocaleStr = null;
		}
		Locale defaultLocaleFromClient = request.getLocale();
		Locale requestLocale = (reqlocaleStr == null) ? null : LocaleUtil.localeFromString(reqlocaleStr,
				defaultLocaleFromClient);
		if (requestLocale != null && !requestLocale.equals(sessionLocale)) {
			sessionBag.setLocale(requestLocale);
		}

		// CtxSessionBag.clear();
		CtxSessionBag.setSessionBag(sessionBag);
	}

	@Override
	public void attributeAdded(HttpSessionBindingEvent event){
		dealSessionErr(event, "add");
	}

	@Override
	public void attributeRemoved(HttpSessionBindingEvent event){
		dealSessionErr(event, "remove");
	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent event){
		dealSessionErr(event, "replace");
	}

	private void dealSessionErr(HttpSessionBindingEvent event, String type){
		if(!Constant.useSessionInMemcache()){
			return;
		}
		if(EXCLUDE_SESSION_NAME.contains(event.getName())){
			return;
		}
		String line = System.getProperty("line.separator");
		StringBuilder sb = new StringBuilder();
		sb.append("------------------------------------").append(line);
		sb.append("don't use session!").append(line);
		sb.append("type:").append(type).append(line);
		sb.append("uri:").append(ServletActionContext.getRequest()!=null?ServletActionContext.getRequest().getRequestURI():"null").append(line);
		sb.append("key:").append(event.getName()).append(line);
		sb.append("value:").append(event.getValue());
		log.error(sb.toString());
	}
}
